package com.qf.shiro;

import com.qf.constant.AppConstant;
import com.qf.entity.UserRole;
import com.qf.entity.BackendUser;
import com.qf.entity.DevUser;
import com.qf.enums.AppEnum;
import com.qf.enums.DevStateEnum;
import com.qf.exception.AppException;
import com.qf.service.BackendUserService;
import com.qf.service.DevUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

@Slf4j
public class DevCustomRealm extends AuthorizingRealm {

    @Autowired
    private DevUserService devUserService;
    @Autowired
    private BackendUserService backendUserService;

    public static void main(String[] args) {
        System.out.println(new Md5Hash("123123","asdfghj",1024).toString());
    }

    //创建对象时自动set进对象里
    {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //加密方式是
        matcher.setHashAlgorithmName("MD5");
        //加密次数是
        matcher.setHashIterations(1024);

        this.setCredentialsMatcher(matcher);
    }
    @Override
    //授权    查询用户的角色和权限
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Object obj = principals.getPrimaryPrincipal();

        if (obj instanceof DevUser){
            return null;
        }
        else if (obj instanceof BackendUser){
            BackendUser backendUser = (BackendUser) obj;
            //获取当前登录用户的id
            Long id = backendUser.getId();
            //根据id查询全部角色信息
            Set<UserRole> roleSet=backendUserService.findRolesById(id);

            //封装数据  全部角色名称  和全部的角色id（用来查询全部权限信息）
            Set<String> roleNames = new HashSet<>();
            Set<Integer> roleIds = new HashSet<>();
            for (UserRole backendRole : roleSet) {
                roleNames.add(backendRole.getRoleName());
                roleIds.add(backendRole.getRoleId());            }

            //根据角色ids查询全部权限信息
            Set<String> permissions =backendUserService.findPermissionsByRoleIds(roleIds);
            //创建返回结果SimpleAuthorizationInfo，并封装角色和权限
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
            info.setStringPermissions(permissions);
            return info;

        }

        return null;

    }



    @Override
    //认证    判断用户是否登录过
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        if (!(token instanceof AppToken)){
            log.info("【用户登录】 用户认证格式不对  token={}",token);
            return null;
        }

        AppToken appToken = (AppToken) token;
        if (AppConstant.DEV_USER.equals(appToken.getModule())){

            //获取用户输入的用户名
            String username = (String) appToken.getPrincipal();
            //根据用户名信息查询用户信息
            DevUser devUser = devUserService.findByUsername(username);
            //判断用户信息是否为空
            if (devUser==null){
                //跳转到登录页面
                return null;
            }
            //判断用户账号是否激活
            if (devUser.getDevState() == DevStateEnum.not_activation.getCode()){
                log.info("【用户登录】 账号未激活！devUser={}",devUser);
                throw new AppException(AppEnum.DEVUSER_NOT_ACTIVE);
            }


            //将正确的user对象和密码封装到AuthenticationInfo对象中
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(devUser,devUser.getDevPassword(),"DevCustomRealm");
            //*******注意盐也要封装到AuthenticationInfo对象中*****
            info.setCredentialsSalt(ByteSource.Util.bytes(devUser.getDevSalt()));
            return info;
        }else if (AppConstant.BACKEND_USER.equals(appToken.getModule())){

            //获取用户输入的用户名
            String username = (String) appToken.getPrincipal();
            //根据用户名信息查询用户信息
            BackendUser backendUser = backendUserService.findByUsername(username);
            //判断用户信息是否为空
            if (backendUser==null){
                //跳转到登录页面
                return null;
            }

            //将正确的user对象和密码封装到AuthenticationInfo对象中
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(backendUser,backendUser.getBackendPassword(),"DevCustomRealm");
            //*******注意盐也要封装到AuthenticationInfo对象中*****
            info.setCredentialsSalt(ByteSource.Util.bytes(backendUser.getBackendSalt()));
            return info;


        }

        return null;
    }


}
